#include "t_generator.h"
//#include "widget.h"
#include "t_box_player.h"

qint64 T_Generator::readData(char *data, qint64 len)
{
    //qDebug() << "[Generator::readData()]" << "[this->pos()]" << this->pos() << "[len]" << len;
    Q_ASSERT(len%2==0);
    //[m_max_seek_size]
    m_max_seek_size = qMax(m_max_seek_size, len);
    //[left_len, read_len]
    int left_len = len;
    int read_len = 0;
    //[pop from m_audio_data_left]
    QByteArray v_result = p_pop_front(m_audio_data_left, left_len);
    left_len -= v_result.size();
    read_len += v_result.size();
    //[decode packet if needed]
    if(left_len>0)
    {
        QByteArray v_packet_bytes = p_readPacket(left_len);
        left_len -= v_packet_bytes.size();
        read_len += v_packet_bytes.size();
        v_result.append(v_packet_bytes);
    }
    //qDebug() << "[Generator::readData()]" << read_len << v_result.size();
    Q_ASSERT(read_len==v_result.size());
    //[save bytes beyond capacity => m_audio_data_left]
    if(v_result.size() > len)
    {
        m_audio_data_left.append(p_pop_back(v_result, v_result.size()-len));
    }
    else if(v_result.size() < len)
    {
        // add silence
        //qDebug() << "[Generator::readData()]:short(1)" << len << v_result.size();
        v_result.append(QByteArray(len-v_result.size(), (char)0));
        //qDebug() << "[Generator::readData()]:short(2)" << len << v_result.size();
    }
    //[append the result bytes => m_audio_last_read (prepare for seek()ing backwards)]
    m_audio_last_read.append(v_result);
    //[reduce m_audio_last_read's size => m_max_seek_size]
    if(m_audio_last_read.size() > m_max_seek_size)
    {
        m_audio_last_read = m_audio_last_read.right(m_max_seek_size);
    }
    //Q_ASSERT(v_result.size()<=len);
    //qDebug() << "[Generator::readData()]" << len << v_result.size();
    Q_ASSERT(v_result.size()==len);
    memcpy(data, v_result.constData(), v_result.size());
    return v_result.size();
}

// In qaudiooutput_win32_p.cpp
// QAudioOutputPrivate::deviceReady() seek() backwards
// (when part of the final read() data could not be written to the sound device)
// Generator::m_audio_last_read (=QByteArray) holds final read() data to handle
// this case.
bool T_Generator::seek(qint64 pos)
{
    qint64 v_curr_pos = this->pos();
    qint64 v_seek_len = v_curr_pos - pos;
    qDebug() << "[Generator::seek()]" << v_seek_len << m_audio_last_read.size();
    if(v_seek_len <= 0)
    {
        qDebug() << "=====>seek() error (1)";
        return false;
    }
    m_max_seek_size = qMax(m_max_seek_size, v_seek_len);
    if(v_seek_len > m_audio_last_read.size())
    {
        qDebug() << "=====>seek() error (2)";
        m_audio_data_left.prepend(m_audio_last_read);
        m_audio_data_left.clear();
        return false;
    }
    m_audio_data_left.prepend(p_pop_back(m_audio_last_read, v_seek_len));
    qDebug() << "=====>seek() ok";
    return true;
}

QByteArray T_Generator::p_readPacket(qint64 wanted_len)
{
    if(!m_player_ctx->m_time_line.isActive())
    {
        //return QByteArray((int)wanted_len, (char)0);
        return QByteArray();
    }
    //[left_len, read_len]
    int left_len = wanted_len;
    int read_len = 0;
    QByteArray v_result;
    if(left_len>0 && m_player_ctx->m_audio.packet_queue.size()>0)
    {
        T_AV_Packet *v_head_packet = m_player_ctx->m_audio.packet_queue.head();
        m_player_ctx->m_time_line.setElapsed(v_head_packet->timing()); //FIXME
    }
    while(left_len>0 && m_player_ctx->m_audio.packet_queue.size()>0)
    {
        T_AV_Packet *v_head_packet = m_player_ctx->m_audio.packet_queue.head();
        QByteArray v_audio_byes = v_head_packet->decodeAudio();
        left_len -= v_audio_byes.size();
        read_len += v_audio_byes.size();
        v_result.append(v_audio_byes);
        delete m_player_ctx->m_audio.packet_queue.dequeue();
    }
    //qDebug() << "[Generator::p_readPacket()]" << "read_len" << v_result.size();
    Q_ASSERT(read_len==v_result.size());
    // v_result.size() might exceed wanted_len.
    return v_result;
}

QByteArray T_Generator::p_pop_front(QByteArray &a_bytes, int a_maxlen)
{
    int v_len = qMin(a_maxlen, a_bytes.size());
    QByteArray v_pop = a_bytes.left(v_len);
    a_bytes = a_bytes.right(a_bytes.size()-v_len);
    return v_pop;
}

QByteArray T_Generator::p_pop_back(QByteArray &a_bytes, int a_maxlen)
{
    int v_len = qMin(a_maxlen, a_bytes.size());
    QByteArray v_pop = a_bytes.right(v_len);
    a_bytes = a_bytes.left(a_bytes.size()-v_len);
    return v_pop;
}
